0x00:前言
CVE-2014-4113是一个非常经典的内核漏洞,本片文章从Poc触发,分析如何构造Exploit,Poc的下载在文末的链接之中,实验平台是Windows 7 x86 sp1本次漏洞是一个释放后重用的漏洞,深入了解这个漏洞对内核的一些利用方法会有不一样的收获
0x01:Poc分析
栈回溯
我们假装不知道Poc源码,运行Poc进行栈回溯观察
1 | 0: kd> g |
查看此时的 esi 情况,发现 esi 此时为 fffffffb,esi+8 处并没有映射内存
1 | 2: kd> r |
我们在IDA里查看函数信息寻找一下这个 fffffffb 是如何产生的,首先找到崩溃点的位置从内向外开始分析,这里可以发现 esi 也就是我们的第一个参数 P
1 | int __stdcall xxxSendMessageTimeout(PVOID P, CHAR MbString, WCHAR UnicodeString, void *Src, unsigned int HighLimit, unsigned int LowLimit, int a7, PVOID Entry) |
我们继续追溯到 xxxSendMessage
函数
1 | unsigned int __stdcall xxxSendMessage(PVOID P, CHAR MbString, WCHAR UnicodeString, void *Src) |
继续往回追溯,我们只关注关键的代码,发现我们的第一个参数来自于xxxMNFindWindowFromPoint
1 | int __stdcall xxxHandleMenuMessages(int a1, int a2, WCHAR UnicodeString) |
我们来观察一下这个函数的返回值,我们的 esi 最后出问题的值就是 fffffffb(-5) 也就是说这个函数返回的是 fffffffb,我们在v5判断的下一句下断点我们可以得到这里的返回值来自xxxSendMessage
函数
1 | int __stdcall xxxMNFindWindowFromPoint(WCHAR UnicodeString, int a2, int a3) |
我们在windbg中下断重新运行Poc之后到达了这里,我们单步查看xxxSendMessage
函数的返回值发现是 fffffffb,通过观察我们发现这里传了一个1EBh的消息
1 | 3: kd> r |
我们查询消息 1EBh 其原型是MN_FINDWINDOWFROMPOINT
,我们现在知道了这个 fffffffb 产生的原因,就是xxxSendMessage
函数处理1EBh 消息的返回值,因为返回的是 fffffffb ,后面cmp edi, [esi+8]
语句又对 0x3 地址进行了访问就造成了蓝屏,这就是漏洞产生的原因
源码分析
我们查看一下 Poc 源码中是如何构造的,先从简单的分析,在main函数中我们可以大致得到如下代码片段,我们首先创建了一个主窗口,又新建了两个菜单并插入了新菜单项,然后我们调用了SetWindowsHookExA
来拦截 1EBh 的消息,具体内容后面分析,最后我们调用了TrackPopupMenu
函数触发漏洞
1 | main() |
我们来看一些有趣的细节,第一个点就是 main_wnd 中的消息处理函数,注释里面写的很清楚,这里首先判断消息是否进入了空闲状态,如果是则通过PostMessageA
函数发送了三次异步消息,模拟了键盘和鼠标的操作从而达到漏洞点
1 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
第二个点就是我们SetWindowsHookExA
拦截 0x1EB 消息,这里SetWindowLongA
设置了一次窗口函数是因为只有在窗口处理函数线程的上下文空间中调用EndMenu
函数才有意义,我们调用EndMenu
函数销毁了这个菜单,此时的win32k!xxxSendMessage
函数进行调用就会失败,上层函数 win32k!xxxMNFindWindowFromPoint
就会返回 fffffffb ,最后到达win32k!xxxHandleMenuMessages
函数的时候再次调用win32k!xxxSendMessage
时就出现了问题
1 | //Destroys the menu and then returns -5, this will be passed to xxxSendMessage which will then use it as a pointer. |
0x02:漏洞利用
接下来就是我们最喜欢的漏洞利用环节了,让我们首先看一个令人兴奋的片段
1 | loc_95DB94E8: |
这个位置是哪里呢?让我用图片给你说明,因为零页可控,所以我们只需要考虑从漏洞点走到利用点,然后在 0x5c 处放置我们的shellcode即可提权
期间我们有两处判断,第一处只需要赋值当前的Win32ThreadInfo
结构即可,第二处判断赋值为4即可,最后放上我们的shellcode即可
1 | DWORD __stdcall ptiCurrent() |
最终的利用代码在 => GitHub
0x03:后记
其实这个漏洞我很早之前就分析过,但是都是分析的成品Exploit,当时不是很了解内核,分析起来非常吃力,现在重新回来分析一次又有不一样的收获,就像我现在分析CVE-2015-0057一样,毫无思绪,分析完这篇之后我会考虑分析CVE-2015-2546,最后再到CVE-2015-0057